﻿using TopGroup.MySharePoint.Data;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Windows.ApplicationModel.Activation;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using TopGroup.MySharePoint.Common;

// La plantilla de elemento Contrato de búsqueda está documentada en http://go.microsoft.com/fwlink/?LinkId=234240

namespace TopGroup.MySharePoint
{
    // TODO: Editar el manifiesto para habilitar la búsqueda
    //
    // El manifiesto del paquete no se pudo actualizar automáticamente. Abra el archivo del manifiesto
    // del paquete y asegúrese de que esté habilitada la compatibilidad con la activación de la búsqueda.
    /// <summary>
    /// En esta página se muestran resultados de la búsqueda cuando se dirige una búsqueda global a esta aplicación.
    /// </summary>
    public sealed partial class Search : LayoutAwarePage
    {
        // Collection of RecipeDataItem collections representing search results
        private Dictionary<string, List<SampleDataItem>> _results = new Dictionary<string, List<SampleDataItem>>();

        public Search()
        {
            this.InitializeComponent();
        }

        private void OnItemClick(object sender, ItemClickEventArgs e)
        {
            // Navigate to the page showing the recipe that was clicked
            this.Frame.Navigate(typeof(ItemDetailPage), ((SampleDataItem)e.ClickedItem).UniqueId);
        }

        /// <summary>
        /// Rellena la página con el contenido pasado durante la navegación. Cualquier estado guardado se
        /// proporciona también al crear de nuevo una página a partir de una sesión anterior.
        /// </summary>
        /// <param name="navigationParameter">Valor de parámetro pasado a
        /// <see cref="Frame.Navigate(Type, Object)"/> cuando se solicitó inicialmente esta página.
        /// </param>
        /// <param name="pageState">Diccionario del estado mantenido por esta página durante una sesión
        /// anterior. Será null la primera vez que se visite una página.</param>
        protected override void LoadState(Object navigationParameter, Dictionary<String, Object> pageState)
        {
            var queryText = navigationParameter as String;

            // TODO: Lógica de búsqueda específica de aplicación. El proceso de búsqueda es el responsable de
            //       crear una lista de categorías de resultados que el usuario pueda seleccionar:
            //
            //       filterList.Add(new Filter("<nombre filtro>", <recuento resultados>));
            //
            //       Solo el primer filtro, normalmente "Todo", debe pasar true como tercer argumento para
            //       empezar en estado activo. Los resultados del filtro activo se proporcionan
            //       en Filter_SelectionChanged, a continuación.

            var filterList = new List<Filter>();
            filterList.Add(new Filter("All", 0, true));

            // Search recipes and tabulate results
            var groups = SampleDataSource.GetGroups("AllGroups");
            string query = queryText.ToLower();
            var all = new List<SampleDataItem>();
            _results.Add("All", all);

            foreach (var group in groups)
            {
                var items = new List<SampleDataItem>();
                _results.Add(group.Title, items);

                foreach (var item in group.Items)
                {
                    if (item.Title.ToLower().StartsWith(query))
                    {
                        all.Add(item);
                        items.Add(item);
                    }
                }
                filterList.Add(new Filter(group.Title, items.Count, false));
            }
            filterList[0].Count = all.Count;

            // Comunicar los resultados mediante el modelo de vista
            this.DefaultViewModel["QueryText"] = '\u201c' + queryText + '\u201d';
            this.DefaultViewModel["Filters"] = filterList;
            this.DefaultViewModel["ShowFilters"] = filterList.Count > 1;
        }

        /// <summary>
        /// Se invoca al seleccionar un filtro con el objeto ComboBox en el estado de vista Snapped.
        /// </summary>
        /// <param name="sender">Instancia de ComboBox.</param>
        /// <param name="e">Datos de evento que describen cómo se cambió el filtro seleccionado.</param>
        void Filter_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            // Determinar el filtro seleccionado
            var selectedFilter = e.AddedItems.FirstOrDefault() as Filter;
            if (selectedFilter != null)
            {
                // Reflejar los resultados en el objeto Filter correspondiente para permitir que la
                // representación de RadioButton usada cuando no está en estado Snapped refleje el cambio
                selectedFilter.Active = true;

                // TODO: Responder al cambio en el filtro activo mediante el establecimiento de this.DefaultViewModel["Results"]
                //       en una colección de elementos con propiedades Image, Title, Subtitle y Description enlazables

                // Garantizar que se encuentran resultados+

                this.DefaultViewModel["Results"] = _results[selectedFilter.Name];


                object results;
                ICollection resultsCollection;
                if (this.DefaultViewModel.TryGetValue("Results", out results) &&
                    (resultsCollection = results as ICollection) != null &&
                    resultsCollection.Count != 0)
                {
                    VisualStateManager.GoToState(this, "ResultsFound", true);
                    return;
                }
            }

            // Mostrar texto informativo cuando no haya resultados de la búsqueda.
            VisualStateManager.GoToState(this, "NoResultsFound", true);
        }

        /// <summary>
        /// Se invoca al seleccionar un filtro con un objeto RadioButton en un estado distinto de Snapped.
        /// </summary>
        /// <param name="sender">Instancia de RadioButton seleccionada.</param>
        /// <param name="e">Datos de evento que describen cómo se seleccionó el objeto RadioButton.</param>
        void Filter_Checked(object sender, RoutedEventArgs e)
        {
            // Reflejar el cambio en el objeto CollectionViewSource usado por el ComboBox
            // correspondiente para asegurarse de que el cambio se refleja en estado Snapped
            if (filtersViewSource.View != null)
            {
                var filter = (sender as FrameworkElement).DataContext;
                filtersViewSource.View.MoveCurrentTo(filter);
            }
        }

        /// <summary>
        /// Modelo de vista que describe uno de los filtros disponibles para ver los resultados de la búsqueda.
        /// </summary>
        private sealed class Filter : BindableBase
        {
            private String _name;
            private int _count;
            private bool _active;

            public Filter(String name, int count, bool active = false)
            {
                this.Name = name;
                this.Count = count;
                this.Active = active;
            }

            public override String ToString()
            {
                return Description;
            }

            public String Name
            {
                get { return _name; }
                set { if (this.SetProperty(ref _name, value)) this.OnPropertyChanged("Description"); }
            }

            public int Count
            {
                get { return _count; }
                set { if (this.SetProperty(ref _count, value)) this.OnPropertyChanged("Description"); }
            }

            public bool Active
            {
                get { return _active; }
                set { this.SetProperty(ref _active, value); }
            }

            public String Description
            {
                get { return String.Format("{0} ({1})", _name, _count); }
            }
        }
    }
}
